package com.yfqy.admin.security.exception;

import cn.hutool.json.JSONUtil;
import com.yfqy.admin.constant.MyConstants;
import com.yfqy.admin.exception.BaseException;
import com.yfqy.admin.domain.vo.common.ExceptionVO;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.io.PrintWriter;

/**
 * @Author: 梁二东
 * @Date: 2025/5/3 12:57
 * @Description: 捕捉Spring security filter chain 中抛出的未知异常
 **/
public class CustomSecurityExceptionHandler extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            filterChain.doFilter(request, response);
        } catch (BaseException e) {
            // 自定义异常
            ExceptionVO exceptionVO = new ExceptionVO();
            exceptionVO.setCode(e.getCode());
            exceptionVO.setMessage("异常信息：" + e.getMessage());
            exceptionVO.setPath(request.getRequestURI());
            exceptionVO.setMethod(request.getMethod());
            response.setContentType(MyConstants.CHARSET_UTF8);
            PrintWriter writer = response.getWriter();
            writer.write(JSONUtil.toJsonStr(exceptionVO));
            writer.flush();
            writer.close();
        } catch (AuthenticationException | AccessDeniedException e) {
            ExceptionVO exceptionVO = new ExceptionVO();
            exceptionVO.setCode(HttpStatus.FORBIDDEN.value());
            exceptionVO.setMessage("异常信息：" + e.getMessage());
            exceptionVO.setPath(request.getRequestURI());
            exceptionVO.setMethod(request.getMethod());
            response.setContentType(MyConstants.CHARSET_UTF8);
            response.setStatus(HttpStatus.FORBIDDEN.value());
            PrintWriter writer = response.getWriter();
            writer.print(JSONUtil.toJsonStr(exceptionVO));
            writer.flush();
            writer.close();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            // 未知异常
            ExceptionVO exceptionVO = new ExceptionVO();
            exceptionVO.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
            exceptionVO.setMessage("异常信息：" + e.getMessage());
            exceptionVO.setPath(request.getRequestURI());
            exceptionVO.setMethod(request.getMethod());
            response.setContentType(MyConstants.CHARSET_UTF8);
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            PrintWriter writer = response.getWriter();
            writer.write(JSONUtil.toJsonStr(exceptionVO));
            writer.flush();
            writer.close();
        }
    }
}
